Skip to content

Develop#2

Merged
devcedrick merged 7 commits into
mainfrom
develop
Jul 8, 2026
Merged

Develop#2
devcedrick merged 7 commits into
mainfrom
develop

Conversation

@devcedrick

@devcedrick devcedrick commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Added a subscriptions home/dashboard with user balance, renewal details, an “Upcoming” carousel, and expandable subscription cards.
    • Introduced reusable subscription/upcoming cards and a “View All” list header.
  • Bug Fixes
    • Enhanced currency, date, and status formatting (including multi-currency conversion with cached exchange rates and safer “not provided” handling).
  • Style/Chores
    • Improved font loading and splash screen behavior, updated safe-area handling on subscription details, and refined global styling (home “add” icon sizing).

Builds out the home screen to display a user's balance, upcoming subscriptions, and a list of all subscriptions. This release introduces interactive subscription cards with expandable details for a comprehensive overview.

New components:
- `ListHeading`: Reusable title with a "View All" action.
- `SubscriptionCard`: Displays individual subscription details, with expand/collapse functionality.
- `UpcomingSubscriptionCard`: Compact view for imminent subscriptions.

Also includes new utility functions for date and status formatting, and updates `global.css` with styles for the new components.
@devcedrick
devcedrick requested review from Copilot and removed request for Copilot July 7, 2026 13:25
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a subscriptions dashboard home screen, new subscription card components, shared formatting utilities and data constants, plus font loading with splash-screen gating and a safe-area update for the subscription details screen.

Changes

Home Dashboard and Subscription Components

Layer / File(s) Summary
Global type definitions
type.d.ts
Adds AppTab, Subscription, SubscriptionCardProps, UpcomingSubscription, UpcomingSubscriptionCardProps, and ListHeadingProps; switches to a type-only react-native import and adds module export.
Formatting utilities
lib/utils/currency.ts, lib/utils/date.ts, lib/utils/status.ts, package.json
Adds formatCurrency, formatSubscriptionDateTime, and formatStatusLabel, plus the dayjs dependency.
Home/subscription data constants and assets
constants/data.ts, constants/images.ts
Adds typed tab data, home/subscription mock data, and an image export module for avatar and splash assets.
Subscription card components
components/ListHeading.tsx, components/SubscriptionCard.tsx, components/UpcomingSubscriptionCard.tsx
Adds the new list heading, subscription summary card, and upcoming subscription card components.
Home and subscription detail screen wiring
app/(tabs)/index.tsx, app/(tabs)/subscriptions/[id].tsx
Rewrites the home tab into a FlatList-based subscriptions dashboard with expandable cards and an upcoming carousel, and wraps subscription details in a styled safe-area container.
Font loading and splash screen
app.json, app/_layout.tsx
Registers PlusJakartaSans fonts and loads them at app startup before hiding the splash screen.
Global stylesheet formatting
global.css
Reformats theme/component rules and changes .home-add-icon from size-12 to size-8.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant HomeScreen
  participant UpcomingSubscriptionCard
  participant SubscriptionCard
  participant formatCurrency

  User->>HomeScreen: open home tab
  HomeScreen->>UpcomingSubscriptionCard: render upcoming list
  UpcomingSubscriptionCard->>formatCurrency: format price
  HomeScreen->>SubscriptionCard: render subscriptions
  User->>SubscriptionCard: tap card
  SubscriptionCard->>HomeScreen: update expandedSubscriptionId
  HomeScreen->>SubscriptionCard: re-render expanded card
Loading

Possibly related PRs

  • devcedrick/subora#1: Also changes app/(tabs)/index.tsx and constants/data.ts, so it likely covers adjacent home-screen work.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is too vague to identify the main change in this pull request. Use a concise, specific title that reflects the primary update, such as adding the subscriptions dashboard and font setup.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
app.json (1)

41-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant native font registration.

This expo-font plugin config embeds native fonts under family names derived from filenames (e.g. PlusJakartaSans-Bold), separate from the useFonts keys (sans-bold, etc.) actually used by the app's styles in app/_layout.tsx/global.css. Since typography relies exclusively on the useFonts-loaded names, this native registration appears unused. Confirm this is intentional (e.g. for a future native-only usage) or drop it to avoid maintaining two separate font registration mechanisms.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app.json` around lines 41 - 54, The expo-font plugin in app.json is
redundantly registering native fonts that are not used by the app’s typography,
since styles in app/_layout.tsx and global.css rely on the names loaded via
useFonts instead. Either remove this native font registration from the expo-font
config or, if it is meant for future native-only usage, make sure the app
actually references those native family names consistently. Use the expo-font
plugin block and the useFonts setup in app/_layout.tsx as the places to align.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/_layout.tsx`:
- Around line 2-23: Keep the splash screen from auto-hiding until font loading
is fully resolved in RootLayout. In app/_layout.tsx, add the
SplashScreen.preventAutoHideAsync call at module scope, then update the
RootLayout/useFonts flow so both the loaded and error states are handled before
calling SplashScreen.hideAsync. Make sure the useFonts hook result is checked
for failure and that the component does not get stuck returning null when font
loading fails.

In `@components/SubscriptionCard.tsx`:
- Around line 46-49: The subscription price display is inflating the amount by
multiplying it by 50 before formatting. Update the rendering in SubscriptionCard
so the amount passed to formatCurrency is the actual price value, unless there
is a documented smaller-unit conversion elsewhere in the component or its props.
Check the price display block and any related pricing calculation to keep the
displayed subscription cost consistent.

In `@components/UpcomingSubscriptionCard.tsx`:
- Around line 5-16: The UpcomingSubscriptionCard price rendering is using a
hard-coded multiplier instead of the subscription’s actual currency. Update
UpcomingSubscriptionCard so the displayed amount uses the existing currency prop
from UpcomingSubscriptionCardProps and pass that through to formatCurrency,
removing the fixed price * 50 conversion. Check the UpcomingSubscriptionCard
component and its formatCurrency call to ensure the value and currency stay
aligned for all subscriptions.

In `@lib/utils/currency.ts`:
- Around line 13-15: The fallback in the currency formatting logic always
hardcodes the peso symbol, so unsupported currencies are mislabeled. Update the
`formatCurrency` fallback in `currency.ts` to use the requested currency
code/symbol from the function input instead of always returning `₱`, and keep
the existing `Intl.NumberFormat` path unchanged for supported currencies.

---

Nitpick comments:
In `@app.json`:
- Around line 41-54: The expo-font plugin in app.json is redundantly registering
native fonts that are not used by the app’s typography, since styles in
app/_layout.tsx and global.css rely on the names loaded via useFonts instead.
Either remove this native font registration from the expo-font config or, if it
is meant for future native-only usage, make sure the app actually references
those native family names consistently. Use the expo-font plugin block and the
useFonts setup in app/_layout.tsx as the places to align.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8cbd17b8-67f9-45d2-b4df-d51d50decdb6

📥 Commits

Reviewing files that changed from the base of the PR and between a02d11a and 2664c06.

⛔ Files ignored due to path filters (2)
  • assets/images/avatar.png is excluded by !**/*.png
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (15)
  • app.json
  • app/(tabs)/index.tsx
  • app/(tabs)/subscriptions/[id].tsx
  • app/_layout.tsx
  • components/ListHeading.tsx
  • components/SubscriptionCard.tsx
  • components/UpcomingSubscriptionCard.tsx
  • constants/data.ts
  • constants/images.ts
  • global.css
  • lib/utils/currency.ts
  • lib/utils/date.ts
  • lib/utils/status.ts
  • package.json
  • type.d.ts

Comment thread app/_layout.tsx Outdated
Comment thread components/SubscriptionCard.tsx
Comment thread components/UpcomingSubscriptionCard.tsx Outdated
Comment thread lib/utils/currency.ts
Comment on lines +13 to +15
} catch {
return `₱${value.toFixed(2)}`;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fallback ignores the requested currency.

If Intl.NumberFormat throws (e.g., invalid/unsupported currency code), the catch block always renders , even for non-PHP currencies like USD — silently mislabeling the amount's currency.

💡 Proposed fix
   } catch {
-    return `₱${value.toFixed(2)}`;
+    const symbol = currency === "PHP" ? "₱" : `${currency} `;
+    return `${symbol}${value.toFixed(2)}`;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch {
return `₱${value.toFixed(2)}`;
}
} catch {
const symbol = currency === "PHP" ? "₱" : `${currency} `;
return `${symbol}${value.toFixed(2)}`;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/utils/currency.ts` around lines 13 - 15, The fallback in the currency
formatting logic always hardcodes the peso symbol, so unsupported currencies are
mislabeled. Update the `formatCurrency` fallback in `currency.ts` to use the
requested currency code/symbol from the function input instead of always
returning `₱`, and keep the existing `Intl.NumberFormat` path unchanged for
supported currencies.

Copilot AI review requested due to automatic review settings July 7, 2026 13:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds the new subscriptions-focused home/dashboard UI (upcoming + all subscriptions), along with supporting utilities (date/status/currency formatting), shared type definitions, and custom font loading/splash handling to polish the app experience.

Changes:

  • Introduces reusable subscription UI components (subscription cards, upcoming cards, list heading) and wires them into the home tab.
  • Adds formatting utilities and the dayjs dependency to standardize date/status/currency display.
  • Adds custom font loading via expo-font and updates styling/theme assets.

Reviewed changes

Copilot reviewed 14 out of 17 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
type.d.ts Adds global app types for tabs, subscriptions, and component props.
package.json Adds dayjs dependency.
package-lock.json Locks dayjs dependency.
lib/utils/status.ts Adds status label formatter.
lib/utils/date.ts Adds subscription date formatter using dayjs.
lib/utils/currency.ts Adds currency formatting helper.
global.css Re-indents/refines theme + component class definitions and sizing.
constants/images.ts Centralizes image imports/exports.
constants/data.ts Adds mock home/subscription data and types the tabs array.
components/UpcomingSubscriptionCard.tsx New upcoming subscription card UI.
components/SubscriptionCard.tsx New expandable subscription card UI.
components/ListHeading.tsx New reusable list header with optional “View All”.
app/(tabs)/subscriptions/[id].tsx Updates subscription details screen to use safe area.
app/(tabs)/index.tsx Replaces placeholder home screen with the new dashboard layout and lists.
app/_layout.tsx Adds font loading + splash screen gating for a polished startup.
app.json Configures expo-font plugin with bundled fonts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread components/UpcomingSubscriptionCard.tsx Outdated
Comment thread components/SubscriptionCard.tsx Outdated
Comment thread components/SubscriptionCard.tsx
Comment thread components/SubscriptionCard.tsx
Comment thread components/SubscriptionCard.tsx
Comment thread lib/utils/currency.ts
Comment thread lib/utils/date.ts
Comment thread components/ListHeading.tsx
Comment thread app/_layout.tsx
Comment thread app/_layout.tsx
…xchange

- Rewrite formatCurrency to accept a source currency and convert to PHP
  using real-time exchange rates via Frankfurter API with static fallback
- Expose initCurrencyRates() for pre-fetching rates on app startup
- Remove hardcoded 50x multiplier from SubscriptionCard
- Wire currency prop into UpcomingSubscriptionCard so prices convert
  correctly instead of defaulting to PHP

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
lib/utils/currency.ts (1)

17-21: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Harden the remote rate fetch.

fetchRates has no res.ok check and no timeout. A non-2xx response (e.g., 5xx) will parse into a body without .rates, silently caching undefined, and a hung connection will keep the promise pending indefinitely. Add a status check and an abort-based timeout so initCurrencyRates reliably falls back to STATIC_RATES.

♻️ Proposed hardening
-async function fetchRates(): Promise<Record<string, number>> {
-  const res = await fetch(`${API_URL}?from=PHP`);
-  const data = await res.json();
-  return data.rates as Record<string, number>;
-}
+async function fetchRates(): Promise<Record<string, number>> {
+  const controller = new AbortController();
+  const timeout = setTimeout(() => controller.abort(), 5000);
+  try {
+    const res = await fetch(`${API_URL}?from=PHP`, { signal: controller.signal });
+    if (!res.ok) {
+      throw new Error(`Frankfurter request failed: ${res.status}`);
+    }
+    const data = await res.json();
+    return data.rates as Record<string, number>;
+  } finally {
+    clearTimeout(timeout);
+  }
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/utils/currency.ts` around lines 17 - 21, Harden fetchRates by checking
res.ok before parsing and by adding an AbortController-based timeout to the
remote request; if the response is non-2xx, times out, or the payload lacks
rates, make fetchRates fail so initCurrencyRates can fall back to STATIC_RATES
instead of caching an undefined result. Use the existing fetchRates and
initCurrencyRates flow to keep the fallback behavior reliable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/UpcomingSubscriptionCard.tsx`:
- Line 19: The pluralization in UpcomingSubscriptionCard is incorrect for a
zero-day renewal because the current daysLeft check falls back to the singular
form for 0. Update the rendering logic around daysLeft so it uses the singular
label only when daysLeft is exactly 1, and uses the plural label for 0 and all
other values.

In `@lib/utils/currency.ts`:
- Around line 32-38: The getRate function in currency.ts currently falls back to
STATIC_RATES when the cache is stale, but it never triggers a refresh path, so
live rates stop updating. Update getRate to detect stale cache and kick off a
non-blocking refresh by reusing initCurrencyRates while still returning the
current cached or static value immediately. Keep the refresh logic isolated so
the existing cachedRates and lastFetched behavior remains intact, and ensure
subsequent calls pick up the updated rates once the background refresh
completes.

---

Nitpick comments:
In `@lib/utils/currency.ts`:
- Around line 17-21: Harden fetchRates by checking res.ok before parsing and by
adding an AbortController-based timeout to the remote request; if the response
is non-2xx, times out, or the payload lacks rates, make fetchRates fail so
initCurrencyRates can fall back to STATIC_RATES instead of caching an undefined
result. Use the existing fetchRates and initCurrencyRates flow to keep the
fallback behavior reliable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a229841-c4c8-4dbf-a1ea-3db8faaf7237

📥 Commits

Reviewing files that changed from the base of the PR and between cd60893 and d2a1c4e.

📒 Files selected for processing (3)
  • components/SubscriptionCard.tsx
  • components/UpcomingSubscriptionCard.tsx
  • lib/utils/currency.ts

Comment thread components/UpcomingSubscriptionCard.tsx
Comment thread lib/utils/currency.ts
@devcedrick
devcedrick merged commit 44e9988 into main Jul 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants